package org.springblade.tms.module.userinfo.base;

import com.baomidou.mybatisplus.core.metadata.IPage;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.logging.log4j.util.Strings;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.entity.UserInfo;
import org.springblade.system.user.feign.IUserClient;
import org.springblade.tms.global.entity.TimeInterval;
import org.springblade.tms.global.enums.ApprovalStatusEnum;
import org.springblade.tms.global.enums.SapActionEnum;
import org.springblade.tms.global.enums.TableNameEnum;
import org.springblade.tms.global.enums.UserTypeEnum;
import org.springblade.tms.global.exception.CommonException;
import org.springblade.tms.global.utils.CreateUserUtil;
import org.springblade.tms.module.approval.entity.TMApproval;
import org.springblade.tms.module.approval.service.IApprovalService;
import org.springblade.tms.module.carrierdriverrelation.entity.TMCarrierDriverRelation;
import org.springblade.tms.module.carrierdriverrelation.service.ICarrierDriverRelationService;
import org.springblade.tms.module.sap.base.SapRequestService;
import org.springblade.tms.module.userinfo.entity.TMUserInfo;
import org.springblade.tms.module.userinfo.service.IUserInfoService;
import org.springblade.tms.module.userinfo.vo.TMUserInfoVO;
import org.springblade.tms.module.userinfo.vo.UserInfoVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @projectName: BladeX
 * @package: org.springblade.tms.module.userinfo.base
 * @className: DriverManagementService
 * @author: yr
 * @description: 司机管理服务
 * @date: 2022/3/8 13:45
 */
@Transactional(rollbackFor = Exception.class)
@Service
@GlobalTransactional
public class DriverManagementService {
	@Resource
	private IUserInfoService userInfoService;
	@Resource
	private ICarrierDriverRelationService carrierDriverRelationService;
	@Resource
	private IUserClient userClient;
	@Resource
	private IApprovalService approvalService;
	@Resource
	private SapRequestService requestService;

	/**
	 * @param userInfo:
	 * @return R
	 * @author yr
	 * @description 新增或修改司机
	 * @date 2022/3/8 13:48
	 */
	public R saveOrUpdate(TMUserInfo userInfo, TMUserInfo one) {

		//userId为空时为新增，不为空时为修改
		userInfo.setApprovalStatus(ApprovalStatusEnum.PENDING_REVIEW.getValue());
		if (userInfo.getId() == null) {
			TMUserInfo tmUserInfo = userInfoService.lambdaQuery().eq(TMUserInfo::getPhone, userInfo.getPhone()).one();
			//验证手机号
			if (tmUserInfo != null) {
				if (one != null && one.getUserType().equals(UserTypeEnum.CARRIER.getValue())) {
					TMCarrierDriverRelation tmCarrierDriverRelation = carrierDriverRelationService.lambdaQuery().eq(TMCarrierDriverRelation::getRelationDriver, tmUserInfo.getId())
						.eq(TMCarrierDriverRelation::getRelationCarrierNo, one.getId()).one();
					if (tmCarrierDriverRelation != null) {
						throw CommonException.throwCommonException("司机已存在");
					}
					R<Object> r = new R<>();
					r.setCode(206);
					r.setSuccess(true);
					r.setMsg("系统中已存在该司机，是否进行绑定？");
					return r;
				} else {
					CommonException.throwCommonException("手机号已存在");
				}
			}
			//判断驾驶证号是否存在
			TMUserInfo driver = userInfoService.lambdaQuery().eq(TMUserInfo::getCertificateDriverNo, userInfo.getCertificateDriverNo()).one();
			if (driver != null) {
				throw CommonException.throwCommonException("驾驶证号已存在");
			}
			userInfo.setUserType(UserTypeEnum.CHAUFFEUR.getValue());
			//在用户服务新增用户
			User user = CreateUserUtil.createUser(userInfo);
			R<String> stringR = userClient.saveUserAndGetID(user);
			Long id = Long.valueOf(stringR.getData());
			userInfo.setParentId(id);
			boolean save = userInfoService.save(userInfo);
			TMUserInfo info = userInfoService.lambdaQuery().select(TMUserInfo::getId).eq(TMUserInfo::getPhone, userInfo.getPhone()).one();
			//新增审批单
			TMApproval approval = new TMApproval();
			approval.setApprovalStatus(ApprovalStatusEnum.PENDING_REVIEW.getValue());
			approval.setRelationId(info.getId());
			approval.setRelationTableName(TableNameEnum.USER_INFO.value());
			approvalService.save(approval);
			//获取当前用户判断是否为承运商，是承运商将该司机绑定给当前用户
			if (one != null && one.getUserType().equals(UserTypeEnum.CARRIER.getValue())) {
				TMCarrierDriverRelation tmCarrierDriverRelation = new TMCarrierDriverRelation();
				tmCarrierDriverRelation.setRelationCarrierNo(one.getId());
				tmCarrierDriverRelation.setRelationDriver(info.getId());
				carrierDriverRelationService.save(tmCarrierDriverRelation);
			}
			return R.status(save);
		} else {
			//验证手机号和驾驶证号
			TMUserInfo tmUserInfo = userInfoService.lambdaQuery().eq(TMUserInfo::getPhone, userInfo.getPhone())
				.ne(TMUserInfo::getId, userInfo.getId()).one();
			if (tmUserInfo != null) {
				CommonException.throwCommonException("手机号已存在");
			}
			TMUserInfo userInfoR = userInfoService.lambdaQuery().eq(TMUserInfo::getCertificateDriverNo, userInfo.getCertificateDriverNo())
				.ne(TMUserInfo::getId, userInfo.getId()).one();
			if (userInfoR != null) {
				CommonException.throwCommonException("驾驶证号已存在");
			}
			//修改用户服务端信息
			TMUserInfo info = userInfoService.lambdaQuery().eq(TMUserInfo::getId, userInfo.getId()).one();
			String tenantId = AuthUtil.getTenantId();
			R<UserInfo> userInfo1 = userClient.userInfo(tenantId, info.getPhone());
			User user = CreateUserUtil.updateUser(userInfo, userInfo1.getData().getUser());
			userClient.updateUser(user);
			boolean update = userInfoService.updateById(userInfo);
			//修改审批单状态为审批中
			TMApproval approval = approvalService.lambdaQuery().eq(TMApproval::getRelationId, userInfo.getId()).one();
			approval.setApprovalStatus(ApprovalStatusEnum.PENDING_REVIEW.getValue());
			approval.setRemarkReject("");
			approvalService.updateById(approval);
			return R.status(update);
		}
	}

	//导入新增司机
	public R save(TMUserInfo userInfo, TMUserInfo one, String postId, String deptId, String roleId) {
		userInfo.setApprovalStatus(ApprovalStatusEnum.PENDING_REVIEW.getValue());
		TMUserInfo tmUserInfo = userInfoService.lambdaQuery().eq(TMUserInfo::getPhone, userInfo.getPhone()).one();
		//验证手机号
		if (tmUserInfo != null) {
			return R.status(false);
		}
		//判断驾驶证号是否存在
		TMUserInfo driver = userInfoService.lambdaQuery().eq(TMUserInfo::getCertificateDriverNo, userInfo.getCertificateDriverNo()).one();
		if (driver != null) {
			return R.status(false);
		}
		userInfo.setUserType(UserTypeEnum.CHAUFFEUR.getValue());
		//在用户服务新增用户
		User user = CreateUserUtil.createUser(userInfo);
		user.setPostId(postId);
		user.setDeptId(deptId);
		user.setRoleId(roleId);
		R<String> stringR = userClient.saveUserAndGetID(user);
		Long id = Long.valueOf(stringR.getData());
		userInfo.setParentId(id);
		boolean save = userInfoService.save(userInfo);
		TMUserInfo info = userInfoService.lambdaQuery().select(TMUserInfo::getId).eq(TMUserInfo::getPhone, userInfo.getPhone()).one();
		//新增审批单
		TMApproval approval = new TMApproval();
		approval.setApprovalStatus(ApprovalStatusEnum.PENDING_REVIEW.getValue());
		approval.setRelationId(info.getId());
		approval.setRelationTableName(TableNameEnum.USER_INFO.value());
		approval.setTenantId(userInfo.getTenantId());
		approvalService.save(approval);
		//获取当前用户判断是否为承运商，是承运商将该司机绑定给当前用户
		if (one != null && one.getUserType().equals(UserTypeEnum.CARRIER.getValue())) {
			TMCarrierDriverRelation tmCarrierDriverRelation = new TMCarrierDriverRelation();
			tmCarrierDriverRelation.setRelationCarrierNo(one.getId());
			tmCarrierDriverRelation.setRelationDriver(info.getId());
			tmCarrierDriverRelation.setTenantId(userInfo.getTenantId());
			carrierDriverRelationService.save(tmCarrierDriverRelation);
		}
		return R.status(save);
	}

	/**
	 * @param userInfo:
	 * @return R
	 * @author yr
	 * @description 查询司机列表
	 * @date 2022/3/8 13:48
	 */
	public R<IPage> list(TMUserInfoVO userInfo, Query query, TimeInterval timeInterval) {
		//即将到期查询参数
		LocalDateTime expireDate = LocalDateTime.now().plusMonths(1);
		List<Long> driverIds = new ArrayList<>();
		if (Strings.isNotBlank(userInfo.getCarrierId())) {
			List<TMCarrierDriverRelation> carrierDriverRelations = carrierDriverRelationService.lambdaQuery()
				.eq(TMCarrierDriverRelation::getRelationCarrierNo, userInfo.getCarrierId()).list();
			driverIds = carrierDriverRelations.stream().map(TMCarrierDriverRelation::getRelationDriver).collect(Collectors.toList());
		}
		TMUserInfo one = getTmUserInfo();
		userInfo.setUserType(UserTypeEnum.CHAUFFEUR.getValue());
		IPage<TMUserInfo> pages = userInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(new TMUserInfo()).lambda()
			.like(userInfo.getName() != null && !userInfo.getName().isEmpty(), TMUserInfo::getName, userInfo.getName())
			.like(userInfo.getPhone() != null && !userInfo.getPhone().isEmpty(), TMUserInfo::getPhone, userInfo.getPhone())
			.eq(userInfo.getApprovalStatus() != null && !userInfo.getApprovalStatus().isEmpty(), TMUserInfo::getApprovalStatus, userInfo.getApprovalStatus())
			.eq(TMUserInfo::getUserType, userInfo.getUserType())
			.ge(timeInterval.getStart() != null, TMUserInfo::getCreateTime, timeInterval.getStart())
			.le(timeInterval.getEnd() != null, TMUserInfo::getCreateTime, timeInterval.getEnd())
			.and(userInfo.getExpireDate(), tmUserInfoLambdaQueryWrapper -> tmUserInfoLambdaQueryWrapper
				.le(TMUserInfo::getIdCardValidEnd, expireDate).or()
				.le(TMUserInfo::getCertificateDriverValidEnd, expireDate))
			.notIn(!driverIds.isEmpty(), TMUserInfo::getId, driverIds)
			.orderByDesc(TMUserInfo::getUpdateTime,TMUserInfo::getId));
		if (one != null && one.getUserType().equals(UserTypeEnum.CARRIER.getValue())) {
			//判断当前用户是否为承运商
			List<TMCarrierDriverRelation> list = carrierDriverRelationService.lambdaQuery()
				.select(TMCarrierDriverRelation::getRelationDriver)
				.eq(TMCarrierDriverRelation::getRelationCarrierNo, one.getId())
				.list();
			List<Long> driverId = list.stream().map(TMCarrierDriverRelation::getRelationDriver).collect(Collectors.toList());
			pages = userInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(new TMUserInfo()).lambda()
				.like(userInfo.getName() != null && !userInfo.getName().isEmpty(), TMUserInfo::getName, userInfo.getName())
				.like(userInfo.getPhone() != null && !userInfo.getPhone().isEmpty(), TMUserInfo::getPhone, userInfo.getPhone())
				.eq(userInfo.getApprovalStatus() != null && !userInfo.getApprovalStatus().isEmpty(), TMUserInfo::getApprovalStatus, userInfo.getApprovalStatus())
				.eq(TMUserInfo::getUserType, userInfo.getUserType())
				.ge(timeInterval.getStart() != null, TMUserInfo::getCreateTime, timeInterval.getStart())
				.le(timeInterval.getEnd() != null, TMUserInfo::getCreateTime, timeInterval.getEnd())
				.in(!driverId.isEmpty(), TMUserInfo::getId, driverId)
				.notIn(!driverIds.isEmpty(), TMUserInfo::getId, driverIds)
				.apply(driverId.isEmpty(), "1=2")
				.orderByDesc(TMUserInfo::getUpdateTime,TMUserInfo::getId));
		}
		pages.getRecords().forEach(userInfo1 -> userInfo1.setApprovalStatus(ApprovalStatusEnum.getDescriptionByValue(userInfo1.getApprovalStatus())));
		//获取审核表的驳回原因
		LinkedList<UserInfoVo> list = new LinkedList<>();
		List<Long> ids = pages.getRecords().stream().map(TMUserInfo::getId).collect(Collectors.toList());
		List<TMApproval> approvalList = approvalService.lambdaQuery().in(!ids.isEmpty(), TMApproval::getRelationId, ids)
			.apply(ids.isEmpty(), "1=2").list();
		Map<Long, String> approvalMap = approvalList.stream().collect(Collectors.toMap(TMApproval::getRelationId, TMApproval::getRemarkReject));
		for (TMUserInfo record : pages.getRecords()) {
			UserInfoVo userInfoVo = BeanUtil.copy(record, UserInfoVo.class);
			userInfoVo.setRemarkReject(approvalMap.get(record.getId()));
			list.add(userInfoVo);
		}
		IPage page = pages;
		page.setRecords(list);
		return R.data(page);
	}

	/**
	 * @param :
	 * @return TMUserInfo
	 * @author yr
	 * @description 获取当前用户
	 * @date 2022/3/8 15:17
	 */
	public TMUserInfo getTmUserInfo() {
		Long userId = AuthUtil.getUser().getUserId();
		return userInfoService.lambdaQuery().eq(TMUserInfo::getParentId, userId).one();
	}

	/**
	 * @param ids:
	 * @return R
	 * @author yr
	 * @description 批量删除司机
	 * @date 2022/3/14 16:19
	 */
	public R delete(List<Long> ids) {
		//判断当前用户是否为承运商
		TMUserInfo tmUserInfo = getTmUserInfo();
		if (tmUserInfo != null && tmUserInfo.getUserType().equals(UserTypeEnum.CARRIER.getValue())) {
			carrierDriverRelationService.remove(Condition.getQueryWrapper(new TMCarrierDriverRelation())
				.lambda().eq(TMCarrierDriverRelation::getRelationCarrierNo, tmUserInfo.getId())
				.in(TMCarrierDriverRelation::getRelationDriver, ids));
			List<TMCarrierDriverRelation> list = carrierDriverRelationService.lambdaQuery().in(TMCarrierDriverRelation::getRelationDriver, ids)
				.select(TMCarrierDriverRelation::getRelationDriver).list();
			List<Long> driverIds = list.stream().map(TMCarrierDriverRelation::getRelationDriver).collect(Collectors.toList());
			ids.removeAll(driverIds);
			if (!ids.isEmpty()) {
				List<TMUserInfo> tmUserInfoList = userInfoService.lambdaQuery().in(TMUserInfo::getId, ids).list();
				deleteUser(tmUserInfoList);
				userInfoService.deleteLogic(ids);
				reportTm(tmUserInfoList);
			}
			return R.status(true);
		} else {
			List<TMUserInfo> tmUserInfoList = userInfoService.lambdaQuery().in(TMUserInfo::getId, ids).list();
			boolean deleteLogic = userInfoService.deleteLogic(ids);
			deleteUser(tmUserInfoList);
			reportTm(tmUserInfoList);
			return R.status(deleteLogic);
		}
	}

	//用户服务删除用户
	private void deleteUser(List<TMUserInfo> tmUserInfoList) {
		List<Long> userIdList = tmUserInfoList.stream().map(TMUserInfo::getParentId).collect(Collectors.toList());
		String userIds = StringUtil.join(userIdList, ",");
		userClient.removeUser(tmUserInfoList.get(0).getTenantId(), userIds);
	}

	//将删除状态上报到tm
	private void reportTm(List<TMUserInfo> tmUserInfoList) {
		R driverMasterData = requestService.driverMasterData(tmUserInfoList, SapActionEnum.D.getValue());
		if (driverMasterData.getMsg().equals("操作失败")) {
			throw CommonException.throwCommonException("上报TM失败");
		}
	}
}
